<?php

    /**
     * TPD v1.1 [2022-06-30]
     * The Tiny-PHP-Database
     *
     * The most tiny CURD database in a single PHP file,
     * who is designed for no-more-service and the simple data managing.
     * Leave your small PHP projects away from MySQL etc.
     *
     * 全球最轻便的PHP单文件级数据库，CURD支持，OOP设计。
     * 数据直接储存在文件中，方便转移管理。 在无数据库服务的PHP空间中可以给你带来惊喜！
     *
     *
     * @author Rudon<285744011@qq.com>
     * @date 2020-08-06
     * 
     * 
     * 【版本】
     *  v1.0 [2020-08-06]
     *  v1.1 [2022-06-30] 
     * 
     *
     * 【特点】
     * 1.纯PHP驱动，无需安装，即放即用；无需后台服务，只占用极少量的I/O资源；
     * 2.TPD密码不限，密码+数据库名为一个组合，决定数据库文件位置，建议使用统一密码；
     * 3.数据库、表、字段等无需提前预设，即插即用；
     * 4.表字段无需提前设计，只需要在插入时全字段插入即可；
     * 5.表字段数据长度、数据类型不限，推荐使用string,int,floor,boolean或者array作为数据类型；
     * 6.TPD数据为明文储存，不适用于机密、金融等项目，请注意数据安全；
     *
     * 
     * 【注意】
     * 1.暂不支持join等联表查询，只支持简单的单表CURD操作
     * 2.暂不支持索引、外键、事务、字符集编码选择、comment注释、SQL语句运行
     * 3.暂不支持字段的Auto-Increase自增、not-null非空、union唯一等特点
     * 4.统一参数$where格式为array('column','how', 'target_value'),其中how操作符可选：
     *   =,!=,>,<,>=,<=,'eq','like','in'
     *   当how为in时，参数`target_value`为数组。
     *
     * 
     * 【ThinkPHP6如何引入extends第三方类】
     *  https://www.tpxhm.com/adetail/870.html
     * 
     * 【使用方法】
     *  详细使用方法在php文件的最后面
     *
     * 
     * 【版本修改】
     *  v1.1 [2022-06-30] 
     *  1）新增 get_next_id() 获取表的下一个自增id
     *  2）修改 getInstance()时可以在第三个参数中指定数据库最终存储目录（绝对路径）
     *  3）修改 select、update、delete的where，接受array('name' => 'Kim')类型的数组
     * 
     * 
     * 
     */

    


    namespace TPD;

    class TPD {
        static private $instance;
        static private $token;

        static public $topFolder;           // src/TPD/data/
        static public $dbFolder;            // src/TPD/data/dbname/0fa279/
        static public $tablePath;           // src/TPD/data/dbname/0fa279/tablename

        static public $dbName = 'dbname';
        static public $tableName;
        static public $table_ext = '.tpd';


        private function __construct() {}
        private function __clone() {}


        /**
         * dbname 数据库名
         * password 绑定密码
         * topFolder 指定所有数据库共用的顶级目录
         */
        static public function getInstance($dbname = NULL, $password = '', $topFolder = NULL)
        {
            /* 数据库名称自定义，默认是'dbname' */
            if (!is_null($dbname)) {
                self::$dbName = str_replace(' ','', strval($dbname));
            }

            /* 初始化 */
            self::setToken($password);
            if ($topFolder === NULL) {
                // 非指派，使用当前目录下的data目录
                self::initEverything();
            } else {
                self::setTopFolder($topFolder);
            }
            

            /* 获取单例 */
            if (!self::$instance instanceof self) {
                self::$instance = new self();
            }

            /* 返回 */
            return self::$instance;
        }

        /**
         * 设置Token - 关系到数据库文件位置 - 关系到是否能正确读取数据库数据
         * @param string $password
         */
        static public function setToken ($password = '')
        {
            (!empty(self::$token))?NULL: self::$token = self::getToken($password);
        }

        /**
         * 获取Token - 根据password变动
         * @param string $password
         */
        static public function getToken ($password = '')
        {
            return substr(md5(strrev(md5(strval($password)))), 0, 6);
        }

        /**
         * 获取当前Token
         * @return mixed
         */
        public function getCurrentToken()
        {
            return self::$token;
        }

        /**
         * 初始化所有的文件for数据库
         * 包括系统顶级目录，和当前token对应的库文件夹，和表文件
         *
         * 数据库文件夹默认是/src/TPD/data/{dbname}/{token}/
         * 表文件默认在 {数据库文件夹}/{表名}
         * *没有后缀名
         * *
         *
         */
        static function initEverything()
        {
            $sep = DIRECTORY_SEPARATOR;
            /* 默认的总目录，./data/ */
            self::$topFolder = __DIR__ . $sep . 'data' . $sep;
            /* 默认的数据库目录，./data/dbname/token/ */
            self::$dbFolder = self::$topFolder . self::$dbName .$sep. self::$token . $sep;

            if (!is_dir(self::$dbFolder)) {
                mkdir(self::$dbFolder, 0750, true);
            }
        }

        /**
         * 自定义数据库文件总目录路径
         * @param null $path 绝对路径
         * @param boolean $is_clean true代表不保留系统自带的同名数据库目录
         */
        static function setTopFolder ($path = NULL, $is_clean = true)
        {
            if (!is_null($path) && is_dir($path)) {
                $sep = DIRECTORY_SEPARATOR;
                $path = rtrim($path, '/\\').$sep;
                self::$topFolder = $path;
                self::$dbFolder = $path . self::$dbName .$sep. self::$token . $sep;

                if (!is_dir(self::$dbFolder)) {
                    mkdir(self::$dbFolder, 0750, true);
                }

                /* 系统自带的同名数据库目录 */
                if ($is_clean) {
                    $default_db_folder = __DIR__.$sep. 'data' .$sep.self::$dbName.$sep.self::$token.$sep;
                    if (is_dir($default_db_folder)) {
                        self::dirDel($default_db_folder);
                    }
                }
            }
        }



        /**
         * 获取当前数据库目录路径
         * @return string 绝对路径
         * 例如 /full/path/to/src/TPD/data/dbname/0fa279/
         */
        static function getTopFolder () {
            return self::$dbFolder;
        }




        /**
         * Delete folder with contant (recursive)
         * @param $path
         */
        static public function dirDel($path) {
            $path = rtrim($path, '/');
            $hand = opendir($path);
            while (($file = readdir($hand)) !== false) {
                if ($file == "." || $file == "..")
                    continue;
                if (is_dir($path . "/" . $file)) {
                    self::dirDel($path . "/" . $file);
                } else {
                    @unlink($path . "/" . $file);
                }
            }
            closedir($hand);
            @rmdir($path);
        }

        /**
         * 错误提示
         * @param string $message
         */
        public function showError($message = 'Unknown ERROR!')
        {
            echo $message;
            die();
        }

        /**
         * 获取表文件路径
         * @param string $table
         * @param bool $autoCreate
         * @return string
         */
        public function getTableFilePathByTable ($table = '', $autoCreate = true)
        {
            /* No space is allowed in the path */
            $table = str_replace(' ','', $table);
            if (empty($table)) {
                self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid table name');
            }

            /* Without extension */
            $path = self::$dbFolder . $table . self::$table_ext;

            /* Auto creating */
            if ($autoCreate && !is_file($path)) {
                file_put_contents($path, json_encode(array()));
            }

            return $path;
        }

        /**
         * 获取表文件路径 - 别名函数
         */
        public function getTP ($table = '', $autoCreate = true) {
            return self::getTableFilePathByTable($table, $autoCreate);
        }

        /**
         * 获取当前表的数据
         * @param string $path
         * @return array
         */
        public function getCurRowsByPath ($path = '') {
            $return = json_decode(file_get_contents($path), true);
            return $return;
        }

        /**
         * 为表 保存新的内容
         * @param string $path
         * @param array $dataArray
         * @return int
         */
        public function savePath($path = '', $dataArray = array())
        {
            file_put_contents($path, json_encode($dataArray));
            return count($dataArray);
        }

        /**
         * 显示所有的数据
         */
        public function showAllData ()
        {
            $data = self::getAllData();
            echo '<h1>All Data</h1>';
            foreach ($data as $oneTableName => $oneTable) {
                echo '<hr/><h3>'.$oneTableName.'</h3>';
                echo '<pre>';
                print_r($oneTable);
                echo '</pre>';
            }
        }

        /**
         * 获取所有的数据 - 以表分开
         * @return array
         */
        public function getAllData ()
        {
            $return = array();
            $tables = self::getTableNames();
            foreach ($tables as $oneT) {
                $return[$oneT] = self::select($oneT);
            }
            return $return;
        }

        /**
         * 获取当前数据库的所有表名字
         * @return array
         */
        public function getTableNames ()
        {
            $return = array();
            $folder = self::$dbFolder;
            $dh = opendir($folder);
            while (($file = readdir($dh)) !== false) {
                if (!in_array($file, array('.','..')) && is_file($folder.$file) && !preg_match('/^\./', $file)) {
                    $return[] = $file;
                }
            }
            closedir($dh);
            return $return;
        }

        /**
         * 数据比较，进行where语句判断
         * @param string $value
         * @param string $how =,!=,>,<,>=,<=,'eq','like','in'
         * @param string $target
         * @return bool
         */
        public function compareValue ($value = '', $how = '=', $target = '')
        {
            $return = false;

            switch (strtolower($how)) {
                case '=':
                case 'eq':
                    if ($value == $target) {
                        $return = true;
                    }
                    break;

                case '!=':
                    if ($value != $target) {
                        $return = true;
                    }
                    break;

                case '!==':
                    if ($value !== $target) {
                        $return = true;
                    }
                    break;

                case '>':
                    if ($value > $target) {
                        $return = true;
                    }
                    break;

                case '<':
                    if ($value < $target) {
                        $return = true;
                    }
                    break;

                case '>=':
                    if ($value >= $target) {
                        $return = true;
                    }
                    break;

                case '<=':
                    if ($value <= $target) {
                        $return = true;
                    }
                    break;

                case 'like':
                    if (stripos($value, $target) !== false) {
                        $return = true;
                    }
                    break;

                case 'in':
                    if(!is_array($target)){
                        self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid array given for case `in`');
                    }
                    if (in_array($value, $target)) {
                        $return = true;
                    }
                    break;

                default:

                    break;
            }
            return $return;
        }


        /**
         * 判断是否单条件查询
         */
        public function check_is_single_where ($where = array()) {
            $res = true;
            if (is_array($where)) {
                foreach ($where as $k=>$v) {
                    if (is_array($v)) {
                        $res = false;
                    }
                }
            }
            return $res;
        }


        /**
         * 检查 + 获取正确的where格式 (统一转二维数组)
         * 
         * @param array $where 
         *   1）单条件查询 - 一维数组 - 两个或者三个数组成员，例如：
         *      $where = array(
         *         'username' => 'Peter'
         *      );
         *      $where = array('id', 1);        --- 这里省略了中间的“=”
         *      $where = array('id', '<=', 1);
         * 
         *   2）多条件查询 - 二维数组 - 多个单条件查询合并的大数组，例如：
         *      $where = array(
         *         'username' => 'Peter',
         *         'age' => 26
         *      );
         * 
         *      $where = array(
         *          array('price', '<=', 100),
         *          array('width', 50)
         *      )
         */
        public function check_and_get_the_standard_where ($where = array()) {
            $return = array();

            /* 检查where格式 */
            if (!is_array($where)) {
                self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid $where: '.json_encode($where));
            }

            /* 特殊情况：空 */
            if (count($where) == 0) {
                return $return;
            }


            /* 先把非数字下标的关联数组（associated array），转为数字下标的数组 */
            /**
             * 例如
             *   $where = array(
             *      'username' => 'Peter',
             *      'age' => 26
             *   ); 
             * 
             *  转为
             *   $where = array(
             *      array('username', '=', 'Peter'),
             *      array('age', '=', 26)
             *   ); 
             * 
             **/ 
            $is_associated_array = false;
            foreach ($where as $k=>$v) {
                if (!is_numeric($k)) {
                    $is_associated_array = true;
                }
            }
            // if( in_array('in', $where) ){die('???');}
            if ($is_associated_array) {
                $tmp = $where;
                $where = array();
                foreach ($tmp as $k=>$v) {
                    $where[] = array(
                        $k,
                        '=',
                        $v
                    );
                }

                // 直接返回即可
                return $where;
            }


            /* 判断是不是一维数组：单条件查询 */
            $is_single_where = self::check_is_single_where($where);

            /* 标准化格式 */
            /* 当where每层数组只有两个属性时，代表中间的“=”已被省略，现在统一扩展为三参数格式，例如 'id', '<=', 1 */

            
            
            /* 检查where数量：  （1/2） 多条件查询 */
            if (!$is_single_where) {
                foreach ($where as $k=>$oneItem) {
                    /* 二级必须是数组 */
                    if (!is_array($oneItem)) {
                        self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid $where: '.json_encode($where));
                    }

                    /* 二或者三个成员 */
                    if (!in_array(count($oneItem), array(2, 3))) {
                        self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid $where: '.json_encode($where));
                    }

                    /* 不全的 */
                    if (count($oneItem) == 2) {
                        // 不排除有下标错乱的一维数组
                        $oneItem = array_values($oneItem);
                        $tmp = array();
                        $tmp[] = $oneItem[0];
                        $tmp[] = '=';
                        $tmp[] = $oneItem[1];

                        $return[] = $tmp;
                    } else {
                        /* 本来就全的 */
                        $return[] = $oneItem;
                    }
                }
            }

            /* 检查where数量：  （2/2） 单条件查询 */
            if ($is_single_where) {
                /* 二或者三个成员 */
                if (!in_array(count($where), array(2, 3))) {
                    self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid $where: '.json_encode($where));
                }

                if (count($where) == 2) {
                    // 不排除有下标错乱的一维数组
                    $where = array_values($where);
                    $tmp = array();
                    $tmp[] = $where[0];
                    $tmp[] = '=';
                    $tmp[] = $where[1];

                    // (统一转二维数组)
                    $return[] = $tmp;
                } else {
                    $return[] = $where;
                }
            }

            return $return;
        }



        /**
         * 判断where是否包含in （只接受一维数组中含in的情况）
         * 
         * @param array $where 一维数组，数组成员数量为3， 第二个是in
         * 例如：
         * $where = array(
         *      'id',
         *      'in',
         *      array(8, 9, 10)
         * );
         * 
         * @return Boolean
         */
        public function check_is_in_where ($where = array()) {
            $res = false;
            // 必须是3个成员 + 包含in
            if (is_array($where) && count($where) == 3 && in_array('in', $where)) {
                // 必须是第二个成员是in
                if (key_exists(1, $where) && strtolower($where[1]) == 'in') {
                    // 第三个成员必须是数组
                    if (key_exists(2, $where) && is_array($where[2])) {
                        // OK
                        $res = true;
                    }
                }
            }
            return $res;
        }


        


        /**
         * 
         * 获取 select
         * 
         * @param string $table
         * 
         * @param array $where 
         *   1）单条件查询 - 一维数组 - 两个或者三个数组成员，例如：
         *      $where = array(
         *         'username' => 'Peter'
         *      );
         *      $where = array('id', 1);        --- 这里省略了中间的“=”
         *      $where = array('id', '<=', 1);
         * 
         *   2）多条件查询 - 二维数组 - 多个单条件查询合并的大数组，例如：
         *      $where = array(
         *         'username' => 'Peter',
         *         'age' => 26
         *      );
         * 
         *      $where = array(
         *          array('price', '<=', 100),
         *          array('width', 50)
         *      )
         * 
         * @return array
         */
        public function select ($table = '', $where = array())
        {
            $return = array();

            // 处理特殊的where in情况
            if (self::check_is_in_where($where)) {
                return self::query_in('select', $table, $where);
            }

            // 检查 + 获取正确的where格式
            $where = self::check_and_get_the_standard_where($where);


            /* 获取所有数据 */
            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);

            /* 筛选 */ 
            if(count($where)){
                /* 多条件查询： 所有条件都要成立 */
                foreach ($now as $oneRow) {
                    // 先假设全都匹配得上
                    $cur_all_cases_matched = true;

                    // 逐条检查筛选条件
                    foreach ($where as $k_where => $one_where) {
                        // 字段匹配得上, 就要连条件也要匹配得上
                        if (key_exists($one_where[0], $oneRow)) {
                            $curV = $oneRow[$one_where[0]];
                            $target = $one_where[2];
                            $how = $one_where[1];
                            if (!self::compareValue($curV, $how, $target)) {
                                // 单反有一个条件不符合，那么当前行就不该为最终结果集成员
                                $cur_all_cases_matched = false;
                            }
                        }
                    }

                    // 如果当前这行数据，全部都符合要求，那么结果集就该有它
                    if ($cur_all_cases_matched) {
                        $return[] = $oneRow;
                    }
                }
                
            } else {
                /* 全部 */
                $return = $now;
            }


            return $return;
        }








        /**
         * 插入
         * @param string $table 
         * @param array $oneRow
         * @return bool
         */
        public function insert ($table, $oneRow = array())
        {
            // $oneRow不允许是二维数组
            foreach ($oneRow as $k=>$v) {
                if (is_array($v)) {
                    self::showError('Invalid $oneRow in insert(), please use bulkInsert() instead: '.json_encode($oneRow));
                }
            }

            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);
            $now[] = $oneRow;
            self::savePath($path, $now);
            return true;
        }

        public function bulkInsert ($table = '', $someRows = array()) {
            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);
            $new = array_merge($now, $someRows);
            self::savePath($path, $new);
            return true;
        }



        /**
         * 删除
         * @param string $table
         * @param array $where
         * @return bool
         */
        public function delete ($table = '', $where = array())
        {
            // 处理特殊的where in情况
            if (self::check_is_in_where($where)) {
                return self::query_in('delete', $table, $where);
            }

            // 检查 + 获取正确的where格式
            $where = self::check_and_get_the_standard_where($where);

            /* 清空表 */
            if(count($where) == 0){
                $path = self::getTP($table);
                file_put_contents($path, json_encode(array()));
                return true;
            }


            /* 获取+判断 */
            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);


            /* 多条件查询： 所有条件都要成立 */
            foreach ($now as $key=>$oneRow) {
                // 先假设全都匹配得上
                $cur_all_cases_matched = true;

                // 逐条检查筛选条件
                foreach ($where as $k_where => $one_where) {
                    // 字段匹配得上, 就要连条件也要匹配得上
                    if (key_exists($one_where[0], $oneRow)) {
                        $curV = $oneRow[$one_where[0]];
                        $target = $one_where[2];
                        $how = $one_where[1];
                        if (!self::compareValue($curV, $how, $target)) {
                            // 单反有一个条件不符合，那么当前行就不该为最终结果集成员
                            $cur_all_cases_matched = false;
                        }
                    }
                }

                // 如果当前这行数据，全部都符合要求，那么结果集就该有它
                if ($cur_all_cases_matched) {
                    unset($now[$key]);
                }
            }



            self::savePath($path, $now);
            return true;
        }

        /**
         * 更新
         * 
         * @param string $table
         * 
         * @param array $where 
         *   0) 当where为空时，当前表所有的数据都要更新
         * 
         *   1）单条件查询 - 一维数组 - 两个或者三个数组成员，例如：
         *      $where = array(
         *         'username' => 'Peter'
         *      );
         *      $where = array('id', 1);        --- 这里省略了中间的“=”
         *      $where = array('id', '<=', 1);
         * 
         *   2）多条件查询 - 二维数组 - 多个单条件查询合并的大数组，例如：
         *      $where = array(
         *         'username' => 'Peter',
         *         'age' => 26
         *      );
         * 
         *      $where = array(
         *          array('price', '<=', 100),
         *          array('width', 50)
         *      )
         * 
         * @param array $toBe
         */
        public function update ($table = '', $where = array(), $toBe = array())
        {
            // 处理特殊的where in情况
            if (self::check_is_in_where($where)) {
                return self::query_in('update', $table, $where, $toBe);
            }

            // 检查 + 获取正确的where格式
            $where = self::check_and_get_the_standard_where($where);


            /* 获取所有数据 */
            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);

            /* 筛选 */
            if(count($where)){
                /* 多条件查询： 所有条件都要成立 */
                foreach ($now as $key=>$oneRow) {
                    // 先假设全都匹配得上
                    $cur_all_cases_matched = true;

                    // 逐条检查筛选条件
                    foreach ($where as $k_where => $one_where) {
                        // 字段匹配得上, 就要连条件也要匹配得上
                        if (key_exists($one_where[0], $oneRow)) {
                            $curV = $oneRow[$one_where[0]];
                            $target = $one_where[2];
                            $how = $one_where[1];
                            if (!self::compareValue($curV, $how, $target)) {
                                // 单反有一个条件不符合，那么当前行就不该为最终结果集成员
                                $cur_all_cases_matched = false;
                            }
                        }
                    }

                    // 如果当前这行数据，全部都符合要求，那么就该update它
                    if ($cur_all_cases_matched) {
                        $newData = $oneRow;
                        foreach ($toBe as $k=>$v){
                            if (key_exists($k, $newData)) {
                                $newData[$k] = $v;
                            }
                        }
                        $now[$key] = $newData;
                    }
                }
                

            } else {
                /* 全都更新 */
                foreach ($now as $key=>$oneRow) {
                    $newData = $oneRow;
                    foreach ($toBe as $k=>$v){
                        if (key_exists($k, $newData)) {
                            $newData[$k] = $v;
                        }
                    }
                    $now[$key] = $newData;
                }
            }


            self::savePath($path, $now);
            return true;
        }




        
        /**
         * 
         * query_in 包括select、update、delete
         * 
         * @param string $action | select、update、delete
         * 
         * @param string $table
         * 
         * @param array $where 一维数组，数组成员数量为3， 第二个是in
         * 例如：
         * $where = array(
         *      'id',
         *      'in',
         *      array(8, 9, 10)
         * );
         * 
         * @param array $tobe 一维数组。 在update的情况下属于更新的数据
         * 例如：
         * $tobe = array( 'name' => 'NEW-NAME', 'age'=>80 );
         * 
         * @return array | select时返回数组，update/delete时返回true
         * 
         */
        public function query_in ($action, $table = '', $where = array(), $tobe = array())
        {
            $return = array();

            // 检查是否in的where
            if (!self::check_is_in_where($where)) {
                self::showError('<font color="#DDD">Line #'.__LINE__.'</font><br/>Invalid $where in query_in(), $action=`'.$action.'`, $where= '.json_encode($where));
            }

            // 转换where为多个where，分别查询
            $in_col = $where[0];
            $in_cases = $where[2];
            foreach ($in_cases as $one_case) {
                // delete
                if ($action == 'delete') {
                    self::delete($table, array($in_col => $one_case));
                }

                // update
                if ($action == 'update') {
                    self::update($table, array($in_col => $one_case), $tobe);
                }
                
                // select
                if ($action == 'select') {
                    // 当前轮查询结果
                    $cur_dbres = self::select($table, array($in_col => $one_case));
                    
                    // 结果去重
                    $return = array_unique(array_merge($return, $cur_dbres), SORT_REGULAR);
                }
            }
            
            
            // 返回
            if ($action == 'select') {
                return $return;
            } else {
                return true;
            }
            
        }




        /**
         * get_next_id
         * 获取表中下一个自增的ID
         * 
         * @param $table 表名
         * @param $col_name 字段名，默认id
         * @return 返回正整数
         */
        public function get_next_id ($table, $col_name = 'id') {
            /* 预设返回id */
            $res = 1;

            /* 获取所有数据 */
            $path = self::getTP($table);
            $now = self::getCurRowsByPath($path);

            /* 循环 */
            $max_id = 0;
            foreach ($now as $oneRow) {
                if (key_exists($col_name, $oneRow)) {
                    $max_id = max($max_id, intval($oneRow[$col_name]));
                }
            }
            $res = $max_id + 1;

            /* 返回 */
            return $res;
        }




    }/* END OF CLASS TPD */






/**
 * =================== 使用方法 ====================
 * // 注意： 如果getInstance时没有带第二参数，密码默认为空字符串
 * // 注意： 建议设置第三参数为绝对路径，以保存文件
 * 
 * include dirname(__DIR__).'/src/TPD/TPD.php';
 * use TPD;
 * $tpd = TPD\TPD::getInstance('DBname', 'password', '/full/path/of/top/folder/for/DB/');
 * 
 *
 * // 查看所有表和数据
 * $tpd->showAllData();
 *
 * $table = 'student';
 * $oneRow = array( 'id' => 1, 'name' => 'Jack', 'age' => 10 );
 * $someRows = array(
 *      array( 'id' => 3, 'name' => 'Peter', 'age' => 8 ),
 *      array( 'id' => 4, 'name' => 'Lucy', 'age' => 9 )
 * );
 *
 * // 0.  清空表
 * $tpd->delete($table);
 *
 * // 1.0 获取表的下一个自增id
 * $next_id = $tpd->get_next_id($table);
 * 
 * // 1.1 插入
 * $tpd->insert($table, $oneRow);
 *
 * // 1.2 批量插入 (建议不要用bulkInsert，因为id自增问题没有优化，不排除会有id重复的现象)
 * $tpd->bulkInsert($table, $someRows);
 *
 * // 2. 查询
 * $result1 = $tpd->select($table, array('id' => 1));
 * $result2 = $tpd->select($table, array('id' => 1, 'name' => 'haha'));
 * $result3 = $tpd->select($table, array('id', '!=', 1));
 * $result4 = $tpd->select($table, array('id', '>', 2));
 * $result5 = $tpd->select($table, array('name', 'like', 'ter'));
 * $result6 = $tpd->select($table, array( array('name', 'like', 'ter'), array('score', '<', 60) ));
 * $result7 = $tpd->select($table, array('id', 'in', array(2,3,4)));
 * $result8 = $tpd->select($table);
 *
 * // 3. 更新
 * $where = array( 'id', 'in', array(7,49,2401) );
 * $where = array( 'id', '=', 3 );
 * $where = array( 'name' => 'King', 'age' => 18 );
 * $toBe = array( 'name' => 'NEW-NAME', 'age'=>80 );
 * $tpd->update($table, $where, $toBe);
 * 
 * 
 * // 4. 删除
 * $where = array( 'id', 'in', array(7,49,2401) );
 * $where = array( 'id', '<', 2 );
 * $where = array( 'id' => 2 );
 * $where = array( 'name' => 'King', 'age' => 18 );
 * $tpd->delete($table, $where);
 * 
 * 
 *
 * 
 * 
 */


